package com.spring.boot.quartz.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.spring.boot.quartz.service.QuartzService;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 定时任务业务逻辑实现
 *
 * @author LiKun
 * @date 2021/7/30 17:01
 */
@Service("quartzService")
public class QuartzServiceImpl implements QuartzService {

    @Resource
    private Scheduler scheduler;

    @Override
    public void pauseAllJob() throws SchedulerException {
        scheduler.pauseAll();
    }

    @Override
    public void resumeAllJob() throws SchedulerException {
        scheduler.resumeAll();
    }

    @Override
    public void pauseJob(JobKey jobKey) throws SchedulerException {
        scheduler.pauseJob(jobKey);
    }

    @Override
    public void resumeJob(JobKey jobKey) throws SchedulerException {
        scheduler.resumeJob(jobKey);
    }

    @Override
    public void deleteJob(JobKey jobKey) throws SchedulerException {
        scheduler.deleteJob(jobKey);
    }

    @Override
    public void triggerJob(JobKey jobKey) throws SchedulerException {
        scheduler.triggerJob(jobKey);
    }

    @Override
    public List<Map<String, String>> queryRunJob() throws SchedulerException {
        List<JobKey> collect = scheduler.getCurrentlyExecutingJobs().stream()
                .map(item -> item.getJobDetail().getKey())
                .collect(Collectors.toList());

        return job2String(collect);
    }

    @Override
    public List<Map<String, String>> queryAllJob() throws SchedulerException {
        return job2String(scheduler.getJobKeys(GroupMatcher.anyGroup()));
    }

    @Override
    public void pauseJobs(GroupMatcher<JobKey> groupMatcher) throws SchedulerException {
        scheduler.pauseJobs(groupMatcher);
    }

    @Override
    public void resumeJobs(GroupMatcher<JobKey> groupMatcher) throws SchedulerException {
        scheduler.resumeJobs(groupMatcher);
    }

    @Override
    public void triggerJob(JobKey jobKey, Map<String, Object> jobData) throws SchedulerException {
        scheduler.triggerJob(jobKey, new JobDataMap(jobData));
    }

    @Override
    public void updateJob(Class<? extends Job> jobClass, String name, String group, String cron, Date date, Map<String, Object> jobData) throws SchedulerException {
        this.deleteJob(new JobKey(name, group));
        this.addJob(jobClass, name, group, cron, date, jobData);
    }

    @Override
    public void addJob(Class<? extends Job> jobClass, String name, String group, String cron, Date date, Map<String, Object> jobData) throws SchedulerException {
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(name, group).build();

        if (CollectionUtil.isNotEmpty(jobData)) {
            jobDetail.getJobDataMap().putAll(jobData);
        }

        Trigger trigger = TriggerBuilder.newTrigger()
                .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                .withIdentity(name, group)
                .startAt(date)
                .build();

        scheduler.scheduleJob(jobDetail, trigger);
    }


    private List<Map<String, String>> job2String(Collection<JobKey> jobKeys) throws SchedulerException {
        List<Map<String, String>> result = new ArrayList<>();

        for (JobKey jobKey : jobKeys) {
            Map<String, String> jobMap = new HashMap<>(4);
            List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);

            for (Trigger trigger : triggers) {
                String expression = null;
                TriggerKey triggerKey = trigger.getKey();
                Trigger.TriggerState state = scheduler.getTriggerState(triggerKey);

                if (trigger instanceof CronTrigger) {
                    expression = ((CronTrigger) trigger).getCronExpression();
                }

                jobMap.put("cron", expression);
                jobMap.put("status", state.name());
                jobMap.put("name", jobKey.getName());
                jobMap.put("group", jobKey.getGroup());
                jobMap.put("trigger", triggerKey.getName());
            }

            result.add(jobMap);
        }

        return result;
    }

}
